package sise.gr1.world.agent.logic;

import static org.junit.Assert.*;

import java.io.IOException;

import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Test;

import CLIPSJNI.Environment;
import CLIPSJNI.MultifieldValue;

public class SalataDigger {

	private static final Logger logger = Logger.getLogger(SalataDigger.class);

	private static final String logicPath = "rules/dSalata.clp";
	private static Environment clips;

	@BeforeClass
	public static void init() {
		logger.info("init invoked");
		String resourcePath = "/src/main/resources/";
		String path = "";
		try {
			path = new java.io.File(".").getCanonicalPath();
		} catch (IOException e) {
			logger.error("Cannot create path to CLIPS file", e);
		}
		clips = new Environment();
		clips.load(path + resourcePath + logicPath);
	}
	
	@Test
	public void ruchyKopanieJedzenie() {
		clips.reset();
		clips.eval("(assert (field (Type ORE) (Resource 1) (PosX 0) (PosY 0)))");
		clips.eval("(assert (field (Type FOOD) (Resource 1) (PosX 1) (PosY 0)))");
		clips.eval("(assert (stat (Name food) (Value 5)))");
		clips.eval("(assert (stat (Name boost) (Value 3)))");
		clips.run();
		MultifieldValue mv = (MultifieldValue) clips
				.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals(result, "move");
		
		clips.reset();
		clips.eval("(assert (field (Type ORE) (Resource 1) (PosX 0) (PosY 0)))");
		clips.eval("(assert (field (Type FOOD) (Resource 1) (PosX 1) (PosY 0)))");
		clips.eval("(assert (stat (Name food) (Value 15)))");
		clips.eval("(assert (stat (Name boost) (Value 3)))");
		
		clips.run();
		clips.eval("(facts)");
		mv = (MultifieldValue) clips
				.eval("(find-all-facts ((?m move)) TRUE)");
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals(result, "collectOre");
		
		clips.reset();
		clips.eval("(assert (field (Type ORE) (Resource 1) (PosX 1) (PosY 0)))");
		clips.eval("(assert (field (Type FOOD) (Resource 1) (PosX 0) (PosY 0)))");
		clips.eval("(assert (stat (Name food) (Value 15)))");
		clips.eval("(assert (stat (Name boost) (Value 3)))");
		
		clips.run();
		clips.eval("(facts)");
		mv = (MultifieldValue) clips
				.eval("(find-all-facts ((?m move)) TRUE)");
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals(result, "collectFood");
		
		clips.reset();
		clips.eval("(assert (field (Type ORE) (Resource 1) (PosX 1) (PosY 0)))");
		clips.eval("(assert (field (Type FOOD) (Resource 1) (PosX 0) (PosY 0)))");
		clips.eval("(assert (stat (Name food) (Value 30)))");
		clips.eval("(assert (stat (Name boost) (Value 3)))");
		
		clips.run();
		clips.eval("(facts)");
		mv = (MultifieldValue) clips
				.eval("(find-all-facts ((?m move)) TRUE)");
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals(result, "move");
	}
	
	@Test
	public void testGlodu() {
		clips.reset();
		clips.eval("(assert (stat (Name food) (Value 2)))");
		clips.eval("(assert (field (Type FOOD) (Resource 1) (PosX 0) (PosY 0)))");
		clips.run();
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("collectFood", result);
	}
	
	@Test
	public void testWyboruNajlepszego() {
		clips.reset();
		clips.eval("(assert (pMove (Move a) (MoveX 0) (MoveY 0) (Priority 800)))");
		clips.eval("(assert (pMove (Move b) (MoveX 0) (MoveY 0) (Priority 1000)))");
		clips.eval("(assert (pMove (Move c) (MoveX 0) (MoveY 0) (Priority 900)))");
		clips.run();
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m pMove)) TRUE)");
		String result = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("b", result);
	}
	
	@Test
	public void testZamiany() {
		clips.reset();
		clips.eval("(assert (field (Type TREE) (Resource 1) (PosX 0) (PosY 0)))");
		clips.eval("(assert (pMove (Move a) (MoveX 0) (MoveY 1) (Priority 800)))");
		clips.eval("(assert (pMove (Move b) (MoveX 0) (MoveY 0) (Priority 1000)))");
		clips.eval("(assert (pMove (Move c) (MoveX 1) (MoveY 0) (Priority 900)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("b", result);
	}
	
	@Test
	public void testUcieczki() {
		clips.reset();
		clips.eval("(assert (visible (Object LOCAL)(PosX -4) (PosY 4)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("1", resultX);
		assertEquals("0", resultY);
	}
	
	@Test
	public void testUcieczkiDiv0() {
		clips.reset();
		clips.eval("(assert (visible (Object LOCAL)(PosX 1) (PosY 0)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("-1", resultX);
		assertEquals("0", resultY);
	}
	
	@Test
	public void testUcieczkiZDrzewem() {
		clips.reset();
		clips.eval("(assert (visible (Object LOCAL)(PosX 4) (PosY 1)))");
		clips.eval("(assert (field (Type TREE) (Resource 1) (PosX -1) (PosY 0)))");
		clips.eval("(assert (field (Type TREE) (Resource 1) (PosX 0) (PosY 1)))");
		clips.eval("(assert (field (Type TREE) (Resource 1) (PosX 0) (PosY -1)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("1", resultX);
		assertEquals("0", resultY);
	}
	@Test
	public void testSumowania() {
		clips.reset();
		clips.eval("(assert (pMove (Move move) (MoveX 1) (MoveY 0)(Priority 200)(ID gen1)))");
		clips.eval("(assert (pMove (Move move) (MoveX 1) (MoveY 0)(Priority 1000)(ID gen2)))");
		clips.eval("(assert (pMove (Move move) (MoveX 1) (MoveY 1)(Priority 1100)(ID gen3)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("1", resultX);
		assertEquals("0", resultY);
	}
	
	@Test
	public void usuwajRuchyWDrzewaIGory() {
		clips.reset();
		clips.eval("(assert (field (Type MOUNTAIN) (Resource 1) (PosX 1) (PosY 0)))");
		clips.eval("(assert (pMove (Move move) (MoveX 1) (MoveY 0)(Priority 1000)))");
		clips.eval("(assert (field (Type TREE) (Resource 1) (PosX 0) (PosY 1)))");
		clips.eval("(assert (pMove (Move move) (MoveX 0) (MoveY 1)(Priority 1000)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips
				.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertNotEquals(result, "move");
	}	
	@Test
	public void nieUsuwajNormalnychRuchow() {
		clips.reset();
		clips.eval("(assert (field (Type MOUNTAIN) (Resource 1) (PosX 1) (PosY 0)))");
		clips.eval("(assert (pMove (Move move) (MoveX 0) (MoveY 1) (Priority 1000)))");
		clips.run();
		MultifieldValue mv = (MultifieldValue) clips
				.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals(result, "move");
	}

	
	
	@Test
	public void testUcieczkiNowy(){
		clips.reset();
		clips.eval("(assert (visible (Object LOCAL)(PosX 0) (PosY 1)))");
		//clips.eval("(assert (field (Type TREE) (Resource 1) (PosX -1.0) (PosY 0)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("1", resultX);
		assertEquals("0", resultY);
	}
	
	@Test
	public void testUcieczkiPrzedDwoma(){
		clips.reset();
		clips.eval("(assert (visible (Object LOCAL)(PosX -1) (PosY 1)))");
		clips.eval("(assert (visible (Object LOCAL)(PosX 0) (PosY -2)))");
		//clips.eval("(assert (field (Type TREE) (Resource 1) (PosX -1.0) (PosY 0)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("1", resultX);
		assertEquals("0", resultY);
	}
	
	
	/*@Test
	public void testZbierania(){
		clips.reset();
		//clips.eval("(assert (visible (Object LOCAL)(PosX -1) (PosY 1)))");
		//clips.eval("(assert (visible (Object LOCAL)(PosX 0) (PosY -2)))");
		clips.eval("(assert (field (Type ORE) (Resource 5) (PosX 2) (PosY 0)))");
		clips.eval("(assert (field (Type ORE) (Resource 1) (PosX -1) (PosY 0)))");
		clips.eval("(assert (stat (Name food) (Value 5)))");
		//clips.eval("(assert (field (Type TREE) (Resource 1) (PosX -1.0) (PosY 0)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("-1", resultX);
		assertEquals("0", resultY);
	}*/
	
	@Test
	public void testPodazania(){
		clips.reset();
		clips.eval("(assert (visible (Object GUARD)(PosX -1) (PosY 1)))");
		clips.eval("(assert (visible (Object GUARD)(PosX 0) (PosY -2)))");
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("move", result);
		assertEquals("0", resultX);
		assertEquals("-1", resultY);
	}
	
	@Test
	public void testActivateBoost(){
		clips.reset();
		clips.eval("(assert (stat (Name food) (Value 20)))");
		clips.eval("(assert (stat (Name boost) (Value 0)))");
		clips.eval("(assert (visible (Object GUARD)(PosX -1) (PosY 1)))");
		clips.eval("(assert (field (Type ORE) (Resource 10) (PosX 0) (PosY 0)))");
		
		clips.run();
		//clips.eval("(facts)");
		MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?m move)) TRUE)");
		String result = "";
		String resultX = "";
		String resultY = "";
		try {
			result = mv.get(0).getFactSlot("Move").getValue().toString();
			resultX = mv.get(0).getFactSlot("MoveX").getValue().toString();
			resultY = mv.get(0).getFactSlot("MoveY").getValue().toString();
		} catch (Exception e) {
		}
		assertEquals("activateBoost", result);
		assertEquals("0", resultX);
		assertEquals("0", resultY);
	}
	


}
